<?php

namespace Modules\Cart\Services;

use Exception;
use Modules\Cart\Entities\Cart;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Request;

class CartService
{
    /**
     * Get all items.
     */
    public function all()
    {
        return Cart::where('user_id', Auth::id());
    }

    /**
     * Add a row to the cart.
     *
     * @param int        $id         Unique ID of the item
     * @param string     $name       Name of the item
     * @param int        $qty        Item qty to add to the cart
     * @param int        $price      Price of one item
     * @param array      $attributes Array of additional attributes, such as 'size' or 'color'...
     *
     * @return string
     */
    public function add(int $good_id, string $channel=null, $name = null, $qty = null, $price = null, array $attributes = [])
    {
        if (!is_numeric($qty) || $qty < 1) {
            throw new Exception('Invalid quantity @ cart.');
        }

        if (!is_numeric($price) || $price < 0) {
            throw new Exception('Invalid price @ cart.');
        }

        $cart = $this->all();
        $rawId = $this->generateRawId($good_id, $channel, $attributes);

        if ($row = $this->get($cart, $rawId)) {
            $row->qty += $qty;
            $row->save();
        } else {
            $row = $this->insertRow($rawId, $channel, $good_id, $name, $qty, $price, $attributes);
        }

        return $row;
    }

    protected function get($cart, $rawId) {
        return $cart->where('__raw_id', $rawId)->first();
    }

    /**
     * 生成raw_id
     *
     * @param integer $goods_id
     * @param string|null $channel
     * @param array $attributes
     * @return void
     */
    protected function generateRawId(int $goods_id, $channel, array $attributes)
    {
        ksort($attributes);
        return md5($goods_id . $channel . serialize($attributes));
    }

    /**
     * Create a new row Object.
     *
     * @param string $rawId      The ID of the new row
     * @param string $id         Unique ID of the item
     * @param string $name       Name of the item
     * @param int    $qty        Item qty to add to the cart
     * @param float  $price      Price of one item
     * @param array  $attributes Array of additional options, such as 'size' or 'color'
     *
     * @return Item
     */
    protected function insertRow($rawId, $channel, $goods_id, $name, $qty, $price, $attributes = [])
    {
        return Cart::create([
            'user_id' => Auth::id(),
            '__raw_id' => $rawId,
            'goods_id' => $goods_id,
            'channel' => $channel,
            'name' =>  $name,
            'qty' => $qty,
            'price' => $price,
            'total' => $qty * $price,
            'attributes' => $attributes,
        ]);
    }
}
